package com.genreate.util.dbUtil;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Page;
import cn.hutool.db.*;
import cn.hutool.db.handler.RsHandler;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.log.level.Level;
import com.genreate.constant.GenConstants;
import com.genreate.util.GenUtils;
import com.genreate.util.VelocityInitializer;
import com.genreate.util.VelocityUtils;
import com.genreate.util.autoBuild.contsant.DatabaseType;
import com.genreate.config.BuildGenConfig;
import com.genreate.config.GenConfig;
import com.genreate.domain.GenTable;
import com.genreate.domain.GenTableColumn;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.StringWriter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

public class DbUtil {
    private static JdbcConfig jdbcConfig = JdbcConfig.mysql_localhost_yys_pump();
//    private static JdbcConfig jdbcConfig = JdbcConfig.sqlserve_65_tl_yhgl_xcgl();

    static {
        //数据库查询 关闭 字段全部转为小写
        GlobalDbConfig.setCaseInsensitive(false);
        GlobalDbConfig.setShowSql(true,true,true, Level.DEBUG);
    }

    public static void setJdbcConfig(JdbcConfig jdbcConfig) {
        DbUtil.jdbcConfig = jdbcConfig;
    }

    /**
     * 找到两个表包含的字段
     *
     * @param table1 表1
     * @param table2 表二
     */
    public static void findTwoTableContains(String table1,String table2) {
        List<String> table1Fileds = getTableFiled(table1);
        List<String> table2Fileds = getTableFiled(table2);
        List<String> list = ListUtil.list(true);
        for (String field : table1Fileds) {
            boolean contains = table2Fileds.contains(field);
            if(contains){
                list.add(field);
            }
        }
//        StringBuilder builder = StrUtil.builder();
//        for (String s : list) {
//            builder.append("d." + s + ",");
//        }
        System.out.println();
    }

    /**
     * 获取表字段
     *
     * @param tableName 表名
     * @return {@link List}<{@link String}>
     */
    public static List<Entity> getTableAllFiled(String tableName){
        String sql = "SELECT 表名=d.name ,\n" +
                "表说明=CASE WHEN a.colorder=1 THEN isnull(f.value,'') ELSE '' END,\n" +
                "字段序号=a.colorder,zdm=a.name,\n" +
                "标识=CASE WHEN COLUMNPROPERTY(a.id,a.name,'IsIdentity')=1 THEN '√' ELSE '' END,\n" +
                "主键=CASE WHEN EXISTS (\n" +
                "SELECT 1 FROM sysobjects WHERE xtype='PK' AND name IN (\n" +
                "SELECT name FROM sysindexes WHERE indid IN (\n" +
                "SELECT indid FROM sysindexkeys WHERE id=a.id AND colid=a.colid))) THEN '√' ELSE '' END,\n" +
                "类型=b.name,\n" +
                "占用字节数=a.length,\n" +
                "长度=COLUMNPROPERTY(a.id,a.name,'PRECISION'),\n" +
                "小数位数=isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),\n" +
                "允许空=CASE WHEN a.isnullable=1 THEN '√' ELSE '' END,\n" +
                "默认值=isnull(e.text,''),\n" +
                "字段说明=isnull(g.[value],'') FROM syscolumns a LEFT JOIN systypes b ON a.xtype=b.xusertype INNER JOIN sysobjects d ON a.id=d.id AND d.xtype='U' AND d.name<> 'dtproperties' LEFT JOIN syscomments e ON a.cdefault=e.id LEFT JOIN sys.extended_properties g ON a.id=g.major_id AND a.colid=g.minor_id LEFT JOIN sys.extended_properties f ON d.id=f.major_id AND f.minor_id =0 WHERE d.name='"+tableName+"'";
        return querys(sql);
    }

    /**
     * 获取表字段
     *
     * @param tableName 表名
     * @return {@link List}<{@link String}>
     */
    public static List<String> getTableFiled(String tableName){
        String sql = "SELECT CASE WHEN col.colorder =1 THEN obj.name ELSE '' END AS 表名,col.colorder AS 序号 ,col.name AS 列名 ,ISNULL(ep.[value],'') AS 列说明 ,t.name AS 数据类型 ,col.length AS 长度 ,ISNULL(COLUMNPROPERTY(col.id,col.name,'Scale'),0) AS 小数位数 ,CASE WHEN COLUMNPROPERTY(col.id,col.name,'IsIdentity')=1 THEN '√' ELSE '' END AS 标识 ,CASE WHEN EXISTS ( " +
                "SELECT 1 FROM dbo.sysindexes si INNER JOIN dbo.sysindexkeys sik ON si.id =sik.id AND si.indid =sik.indid INNER JOIN dbo.syscolumns sc ON sc.id =sik.id AND sc.colid =sik.colid INNER JOIN dbo.sysobjects so ON so.name =si.name AND so.xtype ='PK' WHERE sc.id =col.id AND sc.colid =col.colid) THEN '√' ELSE '' END AS 主键 ,CASE WHEN col.isnullable =1 THEN '√' ELSE '' END AS 允许空 ,ISNULL(comm.text,'') AS 默认值 FROM dbo.syscolumns col" +
                " LEFT JOIN dbo.systypes t ON col.xtype =t.xusertype INNER JOIN dbo.sysobjects obj ON col.id =obj.id AND obj.xtype ='U' AND obj.status >=0 LEFT JOIN dbo.syscomments comm ON col.cdefault =comm.id LEFT JOIN sys.extended_properties ep ON col.id =ep.major_id AND col.colid =ep.minor_id AND ep.name ='MS_Description' LEFT JOIN sys.extended_properties epTwo ON obj.id =epTwo.major_id AND epTwo.minor_id =0 AND epTwo.name ='MS_Description' WHERE obj.name ='"+tableName+"' ORDER BY col.colorder";
        try {
            List<Entity> query = getDb().query(sql);
            return query.stream().map(e->{
                return e.getStr("列名");
            }).collect(Collectors.toList());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    /**
     * 更新
     *
     * @param record 记录
     * @param where  在哪里
     * @return int
     */
    public static int update(Entity record, Entity where){
        try {
            return getDb().update(record,where);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 插入
     *
     * @param records 记录
     * @return int
     */
    public static int[] insert(Collection<Entity> records){
        if(IterUtil.isEmpty(records)){
            return new int[]{-1};
        }
        try {
            return getDb().insert(records);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return new int[]{-1};
    }

    /**
     * 插入
     *
     * @param record 记录
     * @return int
     */
    public static int insert(Entity record){
        try {
            return getDb().insert(record);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * 查询
     *
     * @param sql    查询语句
     * @param params 参数
     * @return 结果对象
     * @throws SQLException SQL执行异常
     * @since 3.1.1
     */
    public static List<Entity> querys(String sql, Object... params){
        try {
            return getDb().query(sql,params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询单条记录
     *
     * @param sql    查询语句
     * @param params 参数
     * @return 结果对象
     * @throws SQLException SQL执行异常
     */
    public static Entity query(String sql, Object... params){
        try {
            return getDb().queryOne(sql,params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 执行非查询语句<br>
     * 语句包括 插入、更新、删除
     *
     * @param sql    SQL
     * @param params 参数
     * @return 影响行数
     * @throws SQLException SQL执行异常
     */
    public static int execute(String sql, Object... params){
        try {
            return getDb().execute(sql,params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 分页查询<br>
     * 查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略
     *
     * @param <T>        结果对象类型
     * @param fields     返回的字段列表，null则返回所有字段
     * @param where      条件实体类（包含表名）
     * @param page       页码，0表示第一页
     * @param numPerPage 每页条目数
     * @param rsh        结果集处理对象
     * @return 结果对象
     * @throws SQLException SQL执行异常
     */
    public static <T> T page(Collection<String> fields, Entity where, int page, int numPerPage, RsHandler<T> rsh){
        try {
            return getDb().page(fields,where,page,numPerPage,rsh);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询<br>
     * 查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略
     *
     * @param <T>        结果对象类型
     * @param where      条件实体类（包含表名）
     * @param page       页码，0表示第一页
     * @param numPerPage 每页条目数
     * @param rsh        结果集处理对象
     * @return 结果对象
     * @throws SQLException SQL执行异常
     * @since 3.2.2
     */
    public static <T> T page(Entity where, int page, int numPerPage, RsHandler<T> rsh){
        try {
            return getDb().page(where,page,numPerPage,rsh);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询<br>
     * 查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略
     *
     * @param <T>   结果对象类型
     * @param where 条件实体类（包含表名）
     * @param page  分页对象
     * @param rsh   结果集处理对象
     * @return 结果对象
     * @throws SQLException SQL执行异常
     * @since 3.2.2
     */
    public static <T> T page(Entity where, cn.hutool.db.Page page, RsHandler<T> rsh){
        try {
            return getDb().page(where,page,rsh);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询<br>
     * 查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略
     *
     * @param <T>    结果对象类型
     * @param fields 返回的字段列表，null则返回所有字段
     * @param where  条件实体类（包含表名）
     * @param page   分页对象
     * @param rsh    结果集处理对象
     * @return 结果对象
     * @throws SQLException SQL执行异常
     */
    public static <T> T page(Collection<String> fields, Entity where, cn.hutool.db.Page page, RsHandler<T> rsh){
        try {
            return getDb().page(fields,where,page,rsh);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询<br>
     *
     * @param <T>    结果对象类型
     * @param sql    SQL构建器，可以使用{@link SqlBuilder#of(CharSequence)} 包装普通SQL
     * @param page   分页对象
     * @param rsh    结果集处理对象
     * @param params 参数
     * @return 结果对象
     * @throws SQLException SQL执行异常
     * @since 5.6.6
     */
    public static <T> T page(CharSequence sql, cn.hutool.db.Page page, RsHandler<T> rsh, Object... params){
        try {
            return getDb().page(sql,page,rsh,params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询
     *
     * @param <T> 处理结果类型，可以将ResultSet转换为给定类型
     * @param sql  SQL构建器
     * @param page 分页对象
     * @param rsh  结果集处理对象
     * @return 结果对象
     * @throws SQLException SQL执行异常
     */
    public static <T> T page(SqlBuilder sql, cn.hutool.db.Page page, RsHandler<T> rsh){
        try {
            return getDb().page(sql,page,rsh);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询
     *
     * @param sql  SQL语句字符串
     * @param page 分页对象
     * @param params 参数列表
     * @return 结果对象
     * @throws SQLException SQL执行异常
     * @since 5.5.3
     */
    public static PageResult<Entity> page(CharSequence sql, cn.hutool.db.Page page, Object... params){
        try {
            return getDb().page(sql,page,params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询
     *
     * @param sql  SQL语句字符串
     * @param pageNum 页数
     * @param pageSize 页码大小
     * @param params 参数列表
     * @return 结果对象
     * @throws SQLException SQL执行异常
     * @since 5.5.3
     */
    public static PageResult<Entity> page(CharSequence sql,int pageNum , int pageSize, Object... params){
        try {
            return getDb().page(sql,new cn.hutool.db.Page(pageNum,pageSize),params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询<br>
     * 查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略
     *
     * @param fields     返回的字段列表，null则返回所有字段
     * @param where      条件实体类（包含表名）
     * @param pageNumber 页码
     * @param pageSize   每页结果数
     * @return 结果对象
     * @throws SQLException SQL执行异常
     */
    public static PageResult<Entity> page(Collection<String> fields, Entity where, int pageNumber, int pageSize){
        try {
            return getDb().page(fields,where,pageNumber,pageSize);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询<br>
     * 查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略
     *
     * @param fields 返回的字段列表，null则返回所有字段
     * @param where  条件实体类（包含表名）
     * @param page   分页对象
     * @return 结果对象
     * @throws SQLException SQL执行异常
     */
    public static PageResult<Entity> page(Collection<String> fields, Entity where, cn.hutool.db.Page page){
        try {
            return getDb().page(fields,where,page);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询<br>
     * 查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略
     *
     * @param where      条件实体类（包含表名）
     * @param page       页码
     * @param numPerPage 每页条目数
     * @return 分页结果集
     * @throws SQLException SQL执行异常
     * @since 3.2.2
     */
    public static PageResult<Entity> page(Entity where, int page, int numPerPage){
        try {
            return getDb().page(where,page,numPerPage);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 分页查询<br>
     * 查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略
     *
     * @param where 条件实体类（包含表名）
     * @param page  分页对象
     * @return 分页结果集
     * @throws SQLException SQL执行异常
     */
    public static PageResult<Entity> page(Entity where, Page page){
        try {
            return getDb().page(where,page);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询到驼峰式大小写
     *
     * @param sql       sql
     * @param beanClass bean类
     * @param params    参数个数
     * @return {@link List}<{@link T}>
     */
    public static <T> List<T> querysToCamelCase(String sql, Class<T> beanClass, Object... params) {
        List<Entity> datas = querys(sql, params);
        return changeEntitys(beanClass, datas);
    }

    /**
     * 改变实体
     *
     * @param beanClass bean类
     * @param datas     数据
     * @return {@link List}<{@link T}>
     */
    public static <T> List<T> changeEntitys(Class<T> beanClass, List<Entity> datas) {
        if(IterUtil.isEmpty(datas)){
            return new ArrayList<>();
        }
        //找到下划线的字段
        List<String> isUnderline = datas.get(0).keySet().stream().filter(e -> e.contains("_")).collect(Collectors.toList());
        if (IterUtil.isEmpty(isUnderline)) {
            return datas.stream().map(e -> e.toBean(beanClass)).collect(Collectors.toList());
        }
        return datas.stream().map(e -> {
            for (String key : isUnderline) {
                //驼峰命名
                String camelKey = CharSequenceUtil.toCamelCase(key);
                e.set(camelKey, e.get(key));
                e.remove(key);
            }
            return e.toBean(beanClass);
        }).collect(Collectors.toList());
    }

    /**
     * 导入表结构
     *
     * @param databaseType 数据库类型
     * @param tableList    表列表
     */
    public static void importGenTable(String databaseType, List<GenTable> tableList) {
        for (GenTable table : tableList) {
            String tableName = table.getTableName();
            GenUtils.initTable(table, "心瘾");
            //保存列信息
            List<GenTableColumn> genTableColumns = getTableColumn(databaseType, tableName);
            List<GenTableColumn> saveColumns = new ArrayList<>();
            for (GenTableColumn column : genTableColumns) {
                GenUtils.initColumnField(column, table);
                saveColumns.add(column);
            }
            if (CollUtil.isNotEmpty(saveColumns)) {
                System.out.println();
            }
        }
    }

    /**
     * 获得表列名 sql语句
     *
     * @param databaseType 数据库类型
     * @param tableName    表名
     * @return {@link String}
     */
    public static String getTableColumnSql(String databaseType, String tableName) {
        String sql = "";
        if (DatabaseType.MYSQL.getType().equals(databaseType)) {
            sql = StrUtil.format("SELECT column_name,(CASE WHEN (is_nullable='no' && column_key !='PRI') THEN '1' ELSE NULL END) AS is_required,(CASE WHEN column_key='PRI' THEN '1' ELSE '0' END) AS is_pk,ordinal_position AS sort,column_comment,(CASE WHEN extra='auto_increment' THEN '1' ELSE '0' END) AS is_increment,column_type FROM information_schema.COLUMNS WHERE table_schema=(\n" +
                    "SELECT DATABASE ()) AND table_name='{}' ORDER BY ordinal_position", tableName);
        } else if (DatabaseType.SQLSERVER.getType().equals(databaseType)) {
            sql = StrUtil.format("SELECT CAST (A.NAME AS nvarchar) AS column_name,CAST (B.NAME AS nvarchar)+(CASE WHEN B.NAME ='numeric' THEN '('+CAST (A.prec AS nvarchar)+','+CAST (A.scale AS nvarchar)+')' ELSE '' END) AS column_type,CAST (G.[VALUE] AS nvarchar) AS column_comment,(\n" +
                    "SELECT 1 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE Z WHERE TABLE_NAME=D.NAME AND A.NAME =Z.column_name) AS is_pk,colorder AS sort FROM SYSCOLUMNS A LEFT JOIN SYSTYPES B ON A.XTYPE =B.XUSERTYPE INNER JOIN SYSOBJECTS D ON A.ID =D.ID AND D.XTYPE='U' AND D.NAME !='DTPROPERTIES' LEFT JOIN SYS.EXTENDED_PROPERTIES G ON A.ID =G.MAJOR_ID AND A.COLID =G.MINOR_ID LEFT JOIN SYS.EXTENDED_PROPERTIES F ON D.ID =F.MAJOR_ID AND F.MINOR_ID =0 " +
                    "WHERE D.NAME ='{}' ORDER BY A.COLORDER", tableName);
        } else {
            throw new RuntimeException(StrUtil.format("不支持{}数据库", databaseType));
        }
        return sql;
    }

    /**
     * 获得表列名
     *
     * @param databaseType 数据库类型
     * @param tableName    表名
     * @return {@link List}<{@link GenTableColumn}>
     */
    public static List<GenTableColumn> getTableColumn(String databaseType, String tableName) {
        String sql = getTableColumnSql(databaseType, tableName);
        return querysToCamelCase(sql, GenTableColumn.class);
    }

    /**
     * 设置主键列信息
     *
     * @param table 业务表信息
     */
    public static void setPkColumn(GenTable table) {
        for (GenTableColumn column : table.getColumns()) {
            if (column.isPk()) {
                table.setPkColumn(column);
                break;
            }
        }
        if (ObjectUtil.isNull(table.getPkColumn())) {
            table.setPkColumn(table.getColumns().get(0));
        }
        if (GenConstants.TPL_SUB.equals(table.getTplCategory())) {
            for (GenTableColumn column : table.getSubTable().getColumns()) {
                if (column.isPk()) {
                    table.getSubTable().setPkColumn(column);
                    break;
                }
            }
            if (ObjectUtil.isNull(table.getSubTable().getPkColumn())) {
                table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
            }
        }
    }

    /**
     * 导入表结构
     *
     * @param databaseType 数据库类型
     * @param table        表
     */
    public static List<GenTableColumn> importGenTable(String databaseType, GenTable table) {
        String tableName = table.getTableName();
        GenUtils.initTable(table, "心瘾");
        //保存列信息
        List<GenTableColumn> genTableColumns = getTableColumn(databaseType, tableName);
        genTableColumns = genTableColumns.stream().peek(e->{
            if(!"1".equals(e.getIsPk())){
                e.setIsPk(null);
            }
        }).collect(Collectors.toList());
        List<GenTableColumn> saveColumns = new ArrayList<>();
        for (GenTableColumn column : genTableColumns) {
            GenUtils.initColumnField(column, table);
            column.setJavaBigField(CharSequenceUtil.upperFirst(column.getJavaField()));
            saveColumns.add(column);
        }
        if (CollUtil.isNotEmpty(saveColumns)) {
            table.setColumns(saveColumns);
            return saveColumns;
        }
        throw new RuntimeException("表列为空");
    }

    /**
     * 查询表信息并生成代码
     *
     */
    public static void generatorCode(BuildGenConfig genConfig) {
        jdbcConfig = genConfig.getJdbcConfig();
        String databaseType = genConfig.getDatabaseType().getType();
        // 查询表信息
        GenTable table = queryToCamelCase(getTableSql(databaseType,genConfig.getTableName()),GenTable.class);
        //将表名转小写
        table.setTableName(table.getTableName().toLowerCase(Locale.ROOT));
        table.setPermissionPrefix(genConfig.getPermissionPrefix());
        //查询表结构
        importGenTable(databaseType,table);
        if(StrUtil.isNotEmpty(genConfig.getPackageName())){
            table.setPackageName(genConfig.getPackageName());
        }
        if(StrUtil.isNotEmpty(genConfig.getModuleName())){
            table.setModuleName(genConfig.getModuleName());
        }
        table.setPathConfig(genConfig.getPathConfig());

        // 设置主键列信息
        setPkColumn(table);
        //初始化-加载classpath目录下的vm文件
        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = GenConfig.getTemplateList(genConfig.getGenType());
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, "UTF-8");
            tpl.merge(context, sw);
            try {
                String pathPrefix = System.getProperty("user.dir");
                if(StrUtil.isNotEmpty(genConfig.getPathPrefix())){
                    pathPrefix = genConfig.getPathPrefix();
                }
                //写文件
                String fileName = pathPrefix + "/src/" +VelocityUtils.getFileName(template, table);

                FileWriter writer = new FileWriter(fileName);
                writer.write(sw.toString());
            } catch (Exception e) {
                System.out.println("渲染模板失败，表名：" + table.getTableName() + e.getMessage());
            }
        }
    }

    /**
     * 查询驼峰式大小写
     *
     * @param sql       sql
     * @param beanClass bean类
     * @param params    参数个数
     * @return {@link T}
     */
    public static <T> T queryToCamelCase(String sql, Class<T> beanClass, Object... params) {
        Entity data = query(sql, params);
        if(ObjectUtil.isEmpty(data)){
            return null;
        }
        //找到下划线的字段
        List<String> isUnderline = data.keySet().stream().filter(e -> e.contains("_")).collect(Collectors.toList());
        if (IterUtil.isEmpty(isUnderline)) {
            return data.toBean(beanClass);
        }
        for (String key : isUnderline) {
            //驼峰命名
            String camelKey = CharSequenceUtil.toCamelCase(key);
            data.set(camelKey, data.get(key));
            data.remove(key);
        }
        return data.toBean(beanClass);
    }

    /**
     * 得到表结构sql
     *
     * @param databaseType 数据库类型
     * @param tableName    表名
     * @return {@link String}
     */
    public static String getTableSql(String databaseType, String[] tableName) {
        String join = ArrayUtil.join(tableName, ",", "'", "'");
        return getTableSql(databaseType, join);
    }

    /**
     * 得到表结构sql
     *
     * @param databaseType 数据库类型
     * @param tableName    表名
     * @return {@link String}
     */
    public static String getTableSql(String databaseType, String tableName) {
        String sql = "";
        if (DatabaseType.MYSQL.getType().equals(databaseType)) {
            sql = StrUtil.format("SELECT table_name,table_comment,create_time,update_time FROM information_schema.TABLES WHERE table_name NOT LIKE 'xxl_job_%' AND table_name NOT LIKE 'gen_%' AND " +
                    "table_schema=(SELECT DATABASE ()) AND table_name = ('{}')", tableName);
        } else if (DatabaseType.SQLSERVER.getType().equals(databaseType)) {
            sql = StrUtil.format("SELECT CAST (D.NAME AS nvarchar) AS table_name,CAST (F.VALUE AS nvarchar) AS table_comment,crdate AS create_time,refdate AS update_time FROM SYSOBJECTS D INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID =F.MAJOR_ID AND F.MINOR_ID =0 AND D.XTYPE ='U' AND D.NAME !='DTPROPERTIES' AND D.NAME NOT LIKE 'xxl_job_%' " +
                    "AND D.NAME NOT LIKE 'gen_%' AND D.NAME = ('{}')", tableName);
        } else {
            throw new RuntimeException(StrUtil.format("不支持{}数据库", databaseType));
        }
        return sql;
    }
    
    public static Db getDb(){
        return Db.use(JdbcDbUtil.getDataSource(jdbcConfig));
    }
}
